package com.youlu.campus.admin.sign.service.impl;

import com.youlu.campus.admin.base.BaseService;
import com.youlu.campus.admin.sign.entity.SignPlanDailyPO;
import com.youlu.campus.admin.sign.entity.SignPlanJoinPO;
import com.youlu.campus.admin.sign.entity.SignPlanPO;
import com.youlu.campus.admin.sign.service.SignPlanService;
import com.youlu.campus.base.base.ConstantsEnum;
import com.youlu.campus.base.base.PageQueryRequest;
import com.youlu.campus.base.sign.SignPlanBase;
import com.youlu.campus.base.sign.dto.SignDailyPageRequest;
import com.youlu.campus.base.sign.dto.SignDailyPageResponse;
import com.youlu.campus.base.sign.dto.SignPlanCreateRequest;
import com.yuelin.infrastructure.quantum.common.QResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author zgz
 * @date 2020/11/18 16:50
 */
@Slf4j
@Service("signPlanService")
public class SignPlanServiceImpl extends BaseService implements SignPlanService {

    @Override
    public QResult createSignPlan(SignPlanCreateRequest createRequest) {
        log.info("createSignPlan createRequest {}", createRequest);
        try {
            if (CollectionUtils.isEmpty(createRequest.getDetails())) {
                return QResult.fail("打卡作业明细不能为空~");
            }
            if (createRequest.getDetails().size() < 3) {
                return QResult.fail("打卡作业明细不能小于3天");
            }
            SignPlanPO signPlanPO = new SignPlanPO();
            signPlanPO.setName(createRequest.getName());
            signPlanPO.setDetails(createRequest.getDetails());
            signPlanPO.setIntroduce(createRequest.getIntroduce());
            signPlanPO.setSort(createRequest.getSort());
            signPlanPO.setCreatedTime(new Date());
            if (createRequest.getDetails() != null) {
                signPlanPO.setTotalDay(createRequest.getDetails().size());
            }
            mongoTemplate.save(signPlanPO);
            return QResult.success(1);
        } catch (Exception e) {
            log.error("createSignPlan error", e);
            return QResult.fail("系统错误");
        }
    }

    @Override
    public QResult editSignPlan(SignPlanCreateRequest createRequest) {
        log.info("editSignPlan createRequest {}", createRequest);
        try {
            if (CollectionUtils.isEmpty(createRequest.getDetails())) {
                return QResult.fail("打卡作业明细不能为空~");
            }
            if (createRequest.getDetails().size() < 3) {
                return QResult.fail("打卡作业明细不能小于3天");
            }
            if (StringUtils.isEmpty(createRequest.getId())) {
                return QResult.fail("参数错误");
            }
            SignPlanPO signPlanPO = mongoTemplate.findById(createRequest.getId(), SignPlanPO.class);
            if (signPlanPO == null) {
                return QResult.fail("参数错误");
            }
            signPlanPO.setName(createRequest.getName());
            signPlanPO.setDetails(createRequest.getDetails());
            signPlanPO.setIntroduce(createRequest.getIntroduce());
            signPlanPO.setSort(createRequest.getSort());
            signPlanPO.setUpdatedTime(new Date());
            if (createRequest.getDetails() != null) {
                signPlanPO.setTotalDay(createRequest.getDetails().size());
            }
            mongoTemplate.save(signPlanPO);
            return QResult.success(1);
        } catch (Exception e) {
            log.error("editSignPlan error", e);
            return QResult.fail("系统错误");
        }
    }

    @Override
    public QResult<Page<SignPlanBase>> getSignPlanList(PageQueryRequest request) {
        log.info("getSignPlanList request {}", request);
        try {
            Query query = new Query();
            long count = mongoTemplate.count(query, SignPlanPO.class);
            PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//            query.with(new Sort(Sort.Direction.DESC, "id"));
            Sort sort=Sort.by(Sort.Direction.DESC, "id");
            query.with(sort);
            List<SignPlanPO> signPlanPOList = mongoTemplate.find(query.with(pageRequest), SignPlanPO.class);
            List<SignPlanBase> list = signPlanPOList.stream().map(signPlanPO -> {
                SignPlanBase response = new SignPlanBase();
                BeanUtils.copyProperties(signPlanPO, response);
                return response;
            }).collect(Collectors.toList());
            return QResult.success(PageableExecutionUtils.getPage(list, pageRequest, () -> count));
        } catch (Exception e) {
            log.error("getSignPlanList error", e);
            return QResult.fail("系统错误");
        }
    }

    @Override
    public QResult<Integer> signPlanStatus(String id, String status) {
        log.info("signPlanStatus id {} status {}", id, status);
        try {
            if (org.apache.commons.lang3.StringUtils.isBlank(id) || org.apache.commons.lang3.StringUtils.isBlank(status)
                    || (!ConstantsEnum.Status.DISABLED.getCode().equalsIgnoreCase(status)
                    && !ConstantsEnum.Status.ENABLED.getCode().equalsIgnoreCase(status))) {
                return QResult.fail("参数错误");
            }
            Query query = new Query();
            query.addCriteria(Criteria.where("id").is(id));
            Update update = new Update();
            update.set("status", status);
            update.set("updatedTime", new Date());
            mongoTemplate.updateFirst(query, update, SignPlanPO.class);
            return QResult.success(1);
        } catch (Exception e) {
            log.error("signPlanStatus error", e);
            return QResult.fail("系统错误");
        }
    }

    @Override
    public QResult<Page<SignDailyPageResponse>> getSignDailyList(SignDailyPageRequest request) {
        log.info("getSignDailyList request {}", request);
        Query query = createQuery(request);
        query.addCriteria(Criteria.where("deleted").is(false));
        long count = mongoTemplate.count(query, SignPlanDailyPO.class);
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "id"));
        Sort sort=Sort.by(Sort.Direction.DESC, "id");
        query.with(sort);
        List<SignPlanDailyPO> dailyPOList = mongoTemplate.find(query.with(pageRequest), SignPlanDailyPO.class);
        List<SignDailyPageResponse> list = dailyPOList.stream().map(dailyPO -> {
            SignDailyPageResponse response = mapperFacade.map(dailyPO, SignDailyPageResponse.class);
            //获取计划名称
            SignPlanPO planPO = mongoTemplate.findById(dailyPO.getSignPlanId(), SignPlanPO.class);
            if (planPO != null) {
                response.setSignPlanName(planPO.getName());
            }
            SignPlanJoinPO joinPO = this.getJoinSignPlanInfo(dailyPO.getUserInfo().getUserId(), dailyPO.getSignPlanId());
            if (joinPO != null) {
                response.setSignCount(joinPO.getSignCount());
            }
            return response;
        }).collect(Collectors.toList());
        return QResult.success(PageableExecutionUtils.getPage(list, pageRequest, () -> count));
    }

    @Override
    public QResult<Integer> SignDailyDisplayed(String signDailyId, boolean displayed) {
        log.info("SignDailyDisplayed signDailyId {} displayed {}", signDailyId, displayed);
        try {
            if (org.apache.commons.lang3.StringUtils.isBlank(signDailyId)) {
                return QResult.fail("参数错误");
            }
            Query query = new Query();
            query.addCriteria(Criteria.where("id").is(signDailyId));
            Update update = new Update();
            update.set("updatedTime", new Date());
            update.set("displayed", displayed);
            mongoTemplate.updateFirst(query, update, SignPlanDailyPO.class);
            return QResult.success(1);
        } catch (Exception e) {
            log.error("SignDailyDisplayed error", e);
            return QResult.fail("系统错误");
        }
    }

    private Query createQuery(SignDailyPageRequest request) {
        Query query = new Query();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(request.getSignType())) {
            query.addCriteria(Criteria.where("signType").is(request.getSignType()));
        }
        if (request.getDisplayed() != null) {
            query.addCriteria(Criteria.where("displayed").is(request.getDisplayed()));
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(request.getKey())) {
            Pattern pattern = Pattern.compile("^.*" + request.getKey() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(new Criteria().orOperator(Criteria.where("userInfo.nickName").regex(pattern),
                    Criteria.where("userInfo.userId").is(request.getKey())));
        }
        if (request.getStartTime() != null || request.getEndTime() != null) {
            Criteria criteria = Criteria.where("createdTime");
            if (request.getStartTime() != null) {
                criteria.gte(request.getStartTime());
            }
            if (request.getEndTime() != null) {
                criteria.lte(request.getEndTime());
            }
            query.addCriteria(criteria);
        }
        return query;
    }

    private SignPlanJoinPO getJoinSignPlanInfo(String userId, String signPlanId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userInfo.userId").is(userId));
        query.addCriteria(Criteria.where("signPlanId").is(signPlanId));
        query.addCriteria(Criteria.where("deleted").is(false));
        return mongoTemplate.findOne(query, SignPlanJoinPO.class);
    }
}
